package com.example.springsecurityjwt.config;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;


/**
 * @author abbys
 * （***）当其他请求发送来，校验token的过滤器，如果校验成功，就让请求继续执行。
 *
 * 1.首先从请求头中提取出 authorization 字段，这个字段对应的value就是用户的token。 就是第一次用户登录成功时，后端写给前端的
 *
 * 2. 将提取出来的token字符串转换为一个Claims对象，再从Claims对象中提取出当前用户名和用户角色，
 *    创建一个UsernamePasswordAuthenticationToken放到当前的Context中，然后执行过滤链使请求继续执行下去。
 *
 *  因为继承了BasicAuthenticationFilter,因此每次只会在登陆之后鉴权时走这个过滤器
 *
 */
public class JwtFilter extends BasicAuthenticationFilter {

    public JwtFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {

        //得到jwttoken的值,前端会把我们生成的token放在请求头中并且用authorization字段
        String jwtToken = request.getHeader("Authorization");

        System.out.println("前端请求头中携带过来的token:"+jwtToken);

        //如果请求头中没有Authorization信息 则直接放行了 或者token不以Bearer开头
        //例如 authorization : Bearer eyJhbGciOiJIUzUxMiJ9.eyJhdXRob3JpdGllcyI6IlJPTEVfYWRtaW4sIiwic3ViIjoiYWRtaW4iLCJleHAiOjE1OTM5NjkxODJ9.RxqttVmpPN9MMH8OO3f7yx2ZcZoElDq3CZ7XYzaqYosL0xx1QIhBF1bgijWiMruFyCCzH6pAzUhKtcOksBHSjg
        if (jwtToken == null || !jwtToken.startsWith("Bearer")) {
            chain.doFilter(request, response);
            return;
        }

        // 如果请求头中有token，则进行解析，并且设置认证信息,和这个被认证用户的权限
        SecurityContextHolder.getContext().setAuthentication(getAuthentication(jwtToken));
        chain.doFilter(request, response);
    }

    /**
     *  这里从token中获取用户信息并新建一个token
     */
    private UsernamePasswordAuthenticationToken getAuthentication(String jwtToken) {

        //String token = jwtToken.replace("Bearer","");

        Claims claims =
                Jwts.parser().setSigningKey("sang@123").parseClaimsJws(jwtToken.replace("Bearer",""))
                .getBody();

        String username = claims.getSubject();   //获取当前登录用户名

        List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList((String) claims.get("authorities")); //得到用户角色

        if(username!=null){
            return new UsernamePasswordAuthenticationToken(username, null,
                    authorities);
        }

        return null;
    }


}